package oojo.data.impl;

import java.lang.reflect.Method;
import java.util.Collection;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class SubRepositoryImpl<E> extends RepositoryImpl<E> {

    private static final Logger logger = LoggerFactory.getLogger(SubRepositoryImpl.class);
    
    private Class<?> parentClass;
    private String parentProperty;
    private String childsProperty;
    
    public Class<?> getParentClass() {
        return parentClass;
    }
    
    public void setParentClass(Class<?> parentClass) {
        this.parentClass = parentClass;
    }
    
    /**
     * Needed when the relation is mapped as 
     * Many-to-One [ One-to-Many (inverse true) ]
     */
    public String getParentProperty() {
        return parentProperty;
    }
    
    public void setParentProperty(String parentProperty) {
        this.parentProperty = parentProperty;
    }
    
    /**
     * Needed when the relation is mapped as 
     * One-to-Many (inverse false) [ Many-to-One ]
     */
    public String getChildsProperty() {
        return childsProperty;
    }
    
    public void setChildsProperty(String childsProperty) {
        this.childsProperty = childsProperty;
    }
    
    @SuppressWarnings("unchecked")
    public void link(Object parent, E child) throws Exception {
        logger.debug("---> link(parent, child)");
        
        Method accessor = null;

        if (parentProperty != null) {
            logger.debug("Binding parent to child");
            accessor = Properties.descriptor(child.getClass(), parentProperty).getWriteMethod();
            accessor.invoke(child, parent);
        }
        
        if (childsProperty != null) {
            logger.debug("Attaching child to parent");
            accessor = Properties.descriptor(parent.getClass(), childsProperty).getReadMethod();
            Collection<E> collection = (Collection<E>) accessor.invoke(parent);
            collection.add(child);
        }            
    }
    
    @SuppressWarnings("unchecked")
    public void unlink(Object parent, E child) throws Exception {
        logger.debug("---> unlink(parent, child)");
        
        Method accessor = null;
        
        if (parentProperty != null) {
            logger.debug("Unbinding parent from child");
            accessor = Properties.descriptor(child.getClass(), parentProperty).getWriteMethod();
            accessor.invoke(child, (Object) null);
        }
        
        if (childsProperty != null) {
            logger.debug("Dettaching child from parent");
            accessor = Properties.descriptor(parent.getClass(), childsProperty).getReadMethod();
            Collection<E> collection = (Collection<E>) accessor.invoke(parent);
            collection.remove(child);
        }            
    }
}
